/**
 ******************************************************************************
 * @file    
 * @author 
 * @Version 
 * @Date    
 * @brief 
 *******************************************************************************  
 **/
#include "zb32l03x_hal.h"
#include "bsp_loop.h"
#include "app_loop.h"

#define USE_DMA  0

#define CONFIG_ADC_CHANNEL_FLAG     (HAL_ADC_IT_CHANNEL_16 )

extern  loopctrlinfo_t loopctrlinfo;

static ADC_HandleTypeDef        LOOPADC_HandleStruct = {0};
#if USE_DMA
HAL_DMA_Handle_TypeDef      LOOPADC_DMA = {0};
#endif
/*
*********************************************************************************************************
*	功能说明: 初始化
*	形    参: 
*	返 回 值: 
* 说    明：
*********************************************************************************************************
*/

void bsp_loop_init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    BASETIM_HandleTypeDef    BaseTim = {0};
    TIM_HandleTypeDef        TIMx = {0};
    TIM_OC_InitTypeDef       TIMxOC = {0};
   
    
    BSP_LOOP_LOOPEN_CLKENABLE();
    
    GPIO_InitStruct.Pin = BSP_LOOP_LOOPEN_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT;
    GPIO_InitStruct.Debounce.Enable = GPIO_DEBOUNCE_DISABLE;
    GPIO_InitStruct.SlewRate = GPIO_SLEW_RATE_HIGH;
    GPIO_InitStruct.DrvStrength = GPIO_DRV_STRENGTH_HIGH;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(BSP_LOOP_LOOPEN_PORT, &GPIO_InitStruct);


    BSP_LOOP_SEND_CLKENABLE();
    GPIO_InitStruct.Pin = BSP_LOOP_SEND_PIN;
    HAL_GPIO_Init(BSP_LOOP_SEND_PORT, &GPIO_InitStruct);

    BSP_LOOP_SAMPLE_TEST_CLKENABLE();
    GPIO_InitStruct.Pin = BSP_LOOP_SAMPLE_TEST_PIN;
    HAL_GPIO_Init(BSP_LOOP_SAMPLE_TEST_PORT, &GPIO_InitStruct);

    BSP_LOOP_SAMPLE_TEST2_CLKENABLE();
    GPIO_InitStruct.Pin = BSP_LOOP_SAMPLE_TEST2_PIN;
    HAL_GPIO_Init(BSP_LOOP_SAMPLE_TEST2_PORT, &GPIO_InitStruct);

    BSP_LOOP_TRIGGERSAMPLE_CLKENABLE();
    GPIO_InitStruct.Pin = BSP_LOOP_TRIGGERSAMPLE_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_AF;
    GPIO_InitStruct.Alternate = BSP_LOOP_TRIGGERSAMPLE_FUN;
    HAL_GPIO_Init(BSP_LOOP_TRIGGERSAMPLE_PORT, &GPIO_InitStruct);


    BSP_LOOP_BACKCODE_TRIGGER_IN_CLKENABLE();
    GPIO_InitStruct.Pin             = BSP_LOOP_BACKCODE_TRIGGER_IN_PIN;
    GPIO_InitStruct.Pull            = GPIO_PULLUP;
    GPIO_InitStruct.Debounce.Enable = GPIO_DEBOUNCE_DISABLE;
    GPIO_InitStruct.SlewRate        = GPIO_SLEW_RATE_HIGH;
    GPIO_InitStruct.DrvStrength     = GPIO_DRV_STRENGTH_HIGH;

    /* Configure Button pin as input with External interrupt */
    GPIO_InitStruct.Mode              = EXTI_MODE;
    GPIO_InitStruct.Exti.Enable       = GPIO_EXTI_INT_ENABLE;
    GPIO_InitStruct.Exti.EdgeLevelSel = GPIO_EXTI_INT_EDGE;
    GPIO_InitStruct.Exti.RiseFallSel  = GPIO_EXTI_INT_HIGHRISE;
    HAL_GPIO_Init(BSP_LOOP_BACKCODE_TRIGGER_IN_PORT, &GPIO_InitStruct);

    __HAL_GPIO_EXTI_CLEAR_FLAG(BSP_LOOP_BACKCODE_TRIGGER_IN_PORT, BSP_LOOP_BACKCODE_TRIGGER_IN_PIN);


    BSP_LOOP_SENDCODE_TIM_CLK_ENABLE();
   /************************** Configure Update frequency: FREQ **********************************/
    /***!!! (HAL_RCC_GetPCLKFreq()/BASETIM_MAXCNTVALUE_16BIT < FREQ < HAL_RCC_GetPCLKFreq()) !!!!**/
    BaseTim.Instance         = BSP_LOOP_SENDCODE_TIM;
    BaseTim.Init.GateEnable  = BASETIM_GATE_DISABLE;
    BaseTim.Init.GateLevel   = BASETIM_GATELEVEL_LOW;
    BaseTim.Init.CntTimSel   = BASETIM_TIMER_SELECT;
    BaseTim.Init.AutoReload  = BASETIM_AUTORELOAD_ENABLE;
    BaseTim.Init.MaxCntLevel = BASETIM_MAXCNTLEVEL_32BIT;
    BaseTim.Init.OneShot     = BASETIM_REPEAT_MODE;
    BaseTim.Init.Prescaler   = BASETIM_PRESCALER_DIV64;
    BaseTim.Init.Period      = BASETIM_MAXCNTVALUE_32BIT;
    HAL_BASETIM_Base_Init(&BaseTim);
    BSP_LOOP_SENDCODE_TIM_DISABLE();
    BSP_LOOP_SENDCODE_TIM->CR |= (BASETIM_CR_INTEN);//interrupt enable
    HAL_NVIC_SetPriority(BSP_LOOP_SENDCODE_TIM_IRQn, PRIORITY_HIGHEST);
    HAL_NVIC_EnableIRQ(BSP_LOOP_SENDCODE_TIM_IRQn); //NVIC Interrupt enable


    BSP_LOOP_BACKCODE_TRIGGERSAMPLE_TIM_CLK_ENABLE();

    TIMx.Instance               = BSP_LOOP_BACKCODE_TRIGGERSAMPLE_TIM;
    TIMx.Init.Period            = APP_LOOP_BACKCODE_SAMPLE_GAP;                              // TIM2B_ARR Period
    TIMx.Init.Prescaler         = (uint32_t)(HAL_RCC_GetPCLKFreq() / 1000000) - 1;                             // TIMx Frequency(CK_CNT) = fCK_PSC/(PSC[15:0]+1) = TIMx_FREQ
    TIMx.Init.ClockDivision     = 0;                               // CKD(Clock division)
    TIMx.Init.CounterMode       = TIM_COUNTERMODE_UP;              // Edge alignment mode ,counter up
    TIMx.Init.RepetitionCounter = 0;                               // TIM1A_RCR
    TIMx.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;   // Enable Auto-reload
    HAL_TIM_PWM_Init(&TIMx);

    TIMxOC.OCMode     = TIM_OCMODE_PWM1;                         // PWM mode1 TIM1A_CCMR1
    TIMxOC.Pulse      = TIMx.Init.Period / 2;                                 // This value is used to determine the duty cycle,and the default duty cycle is 50%
    TIMxOC.OCPolarity = TIM_OCPOLARITY_LOW;                      // Output polarity, OC1 is valid at low level

    HAL_TIM_PWM_ConfigChannel(&TIMx, &TIMxOC, BSP_LOOP_TRIGGERSAMPLE_CH); // Configure TIM1A Channel1
    HAL_TIM_PWM_Start(&TIMx, BSP_LOOP_TRIGGERSAMPLE_CH); //Open PWM Channel1


    BSP_LOOP_BACKCODE_DELAYSAMPLE_TIM_CLK_ENABLE();
   /************************** Configure Update frequency: FREQ **********************************/
    /***!!! (HAL_RCC_GetPCLKFreq()/BASETIM_MAXCNTVALUE_16BIT < FREQ < HAL_RCC_GetPCLKFreq()) !!!!**/
    BaseTim.Instance         = BSP_LOOP_BACKCODE_DELAYSAMPLE_TIM;
    BaseTim.Init.GateEnable  = BASETIM_GATE_DISABLE;
    BaseTim.Init.GateLevel   = BASETIM_GATELEVEL_LOW;
    BaseTim.Init.CntTimSel   = BASETIM_TIMER_SELECT;
    BaseTim.Init.AutoReload  = BASETIM_AUTORELOAD_DISABLE;
    BaseTim.Init.MaxCntLevel = BASETIM_MAXCNTLEVEL_32BIT;
    BaseTim.Init.OneShot     = BASETIM_ONESHOT_MODE;
    BaseTim.Init.Prescaler   = BASETIM_PRESCALER_DIV64;
    BaseTim.Init.Period      = BASETIM_MAXCNTVALUE_32BIT;
    HAL_BASETIM_Base_Init(&BaseTim);
    BSP_LOOP_BACKCODE_DELAYSAMPLE_TIM_DISABLE();
    BSP_LOOP_BACKCODE_DELAYSAMPLE_TIM->CR |= (BASETIM_CR_INTEN);//interrupt enable
    HAL_NVIC_SetPriority(BSP_LOOP_BACKCODE_DELAYSAMPLE_IRQn, PRIORITY_LOW);
    HAL_NVIC_EnableIRQ(BSP_LOOP_BACKCODE_DELAYSAMPLE_IRQn); //NVIC Interrupt enable
   
    

    __HAL_RCC_ADC_CLK_ENABLE();
    BSP_LOOP_BACKCODE_CLKENABLE();
    GPIO_InitStruct.Pin = BSP_LOOP_BACKCODE_PIN;
    GPIO_InitStruct.Mode            = GPIO_MODE_ANALOG;
    GPIO_InitStruct.OpenDrain       = GPIO_OPENDRAIN;
    GPIO_InitStruct.Debounce.Enable = GPIO_DEBOUNCE_DISABLE;
    GPIO_InitStruct.SlewRate        = GPIO_SLEW_RATE_HIGH;
    GPIO_InitStruct.DrvStrength     = GPIO_DRV_STRENGTH_HIGH;
    GPIO_InitStruct.Pull            = GPIO_NOPULL;
    HAL_GPIO_Init(BSP_LOOP_BACKCODE_PORT, &GPIO_InitStruct);


#if USE_DMA 
    LOOPADC_HandleStruct.Instance                = ADC;
    LOOPADC_HandleStruct.Init.SamplingTime       = HAL_ADC_SAMPLE_8CYCLE;
    LOOPADC_HandleStruct.Init.AChannelSel        = BSP_LOOP_BACKCODE_CH;
    LOOPADC_HandleStruct.Init.ClkSel             = HAL_ADC_CLOCK_PCLK_DIV4;
    LOOPADC_HandleStruct.Init.ConvMode           = HAL_ADC_MODE_SINGLE;
    LOOPADC_HandleStruct.Init.AutoAccumulation   = HAL_ADC_AUTOACC_DISABLE;
    LOOPADC_HandleStruct.Init.CircleMode         = HAL_ADC_MULTICHANNEL_NONCIRCLE;
#else      
     
    //10us采样一次
    LOOPADC_HandleStruct.Instance                = ADC;
    LOOPADC_HandleStruct.Init.SamplingTime       = HAL_ADC_SAMPLE_8CYCLE;
    LOOPADC_HandleStruct.Init.AChannelSel        = BSP_LOOP_BACKCODE_CH;
    LOOPADC_HandleStruct.Init.ClkSel             = HAL_ADC_CLOCK_PCLK_DIV4;
    LOOPADC_HandleStruct.Init.ConvMode           = HAL_ADC_MODE_SINGLE;
    LOOPADC_HandleStruct.Init.AutoAccumulation   = HAL_ADC_AUTOACC_DISABLE;
    LOOPADC_HandleStruct.Init.CircleMode         = HAL_ADC_MULTICHANNEL_NONCIRCLE;
#endif
    LOOPADC_HandleStruct.Init.Vref               = HAL_ADC_VREF_VCAP;
    LOOPADC_HandleStruct.Init.ExtTrigConv0       = HAL_ADC_EXTTRIG_PB5_INT;
    
    HAL_ADC_Init(&LOOPADC_HandleStruct);

#if USE_DMA
     /* Configure dma */
    __HAL_RCC_DMA_CLK_ENABLE();
    LOOPADC_DMA.Instance = PDMA;
    HAL_DMA_Init(&LOOPADC_DMA);
    
    HAL_NVIC_EnableIRQ(PDMA_IRQn);

    __HAL_ADC_CLR_IT_FLAG(&LOOPADC_HandleStruct, CONFIG_ADC_CHANNEL_FLAG);

    __HAL_LINKDMA(&LOOPADC_HandleStruct, pHDMA, LOOPADC_DMA);

    HAL_DMA_Channel_Cfg_TypeDef     dma_chnnl = {0};
    dma_chnnl.is_burst_mode          = RESET;
    dma_chnnl.is_channel_switch      = RESET;
    dma_chnnl.is_enable_interrupt    = SET;
    dma_chnnl.is_high_priority       = RESET;
    dma_chnnl.is_peri_trigger        = RESET;
    HAL_DMA_Set_Channel(&LOOPADC_DMA, HAL_DMA_CHANNEL_ADC, &dma_chnnl);
#else
    HAL_NVIC_SetPriority(ADC_IRQn, PRIORITY_HIGH);
    HAL_NVIC_EnableIRQ(ADC_IRQn); //NVIC Interrupt enable
#endif

    


    //HAL_ADC_Init(&LOOPADC_HandleStruct);
    
    bsp_loop_backcodesamplestop();
    
}

/*
*********************************************************************************************************
*	功能说明: 回码初始化
*	形    参: 
*	返 回 值: 
*   说    明：
*********************************************************************************************************
*/
void bsp_loop_backcodesampleinit(void)
{
    __HAL_GPIO_EXTI_CLEAR_FLAG(BSP_LOOP_BACKCODE_TRIGGER_IN_PORT, BSP_LOOP_BACKCODE_TRIGGER_IN_PIN);
    HAL_ADC_Init(&LOOPADC_HandleStruct);
    __HAL_ADC_CLR_IT_FLAG(&LOOPADC_HandleStruct, CONFIG_ADC_CHANNEL_FLAG);
   
}
/*
*********************************************************************************************************
*	功能说明: 回码停止
*	形    参: 
*	返 回 值: 
*   说    明：
*********************************************************************************************************
*/
void bsp_loop_backcodesamplestop(void)
{
    BSP_LOOP_BACKCODE_TRIGGERSAMPLE_TIM_DISABLE();
    BSP_LOOP_BACKCODE_DELAYSAMPLE_TIM_DISABLE();
    //HAL_ADC_Stop_IT(&LOOPADC_HandleStruct);
}



/*
*********************************************************************************************************
*	功能说明: 开始采样回码
*	形    参: 
*	返 回 值: 
* 说    明：
*********************************************************************************************************
*/
void bsp_loop_backcodesamplestart(void)
{
    __HAL_GPIO_EXTI_CLEAR_FLAG(BSP_LOOP_BACKCODE_TRIGGER_IN_PORT, BSP_LOOP_BACKCODE_TRIGGER_IN_PIN);
   
    #if USE_DMA
    HAL_ADC_Start_DMA(&g_hADC, g_adc_value, 24);
    #else
    SET_BIT(ADC->INTCLR, CONFIG_ADC_CHANNEL_FLAG);
    SET_BIT(ADC->INTEN, CONFIG_ADC_CHANNEL_FLAG);
    SET_BIT(ADC->CR0, ADC_CR0_ADCEN);
    #endif
}
/******************************************************************************/
/* ZB32L03x Peripheral Interrupt Handlers                                    */
/* Add here the Interrupt Handlers for the used peripherals.                  */
/* For the available peripheral interrupt handler names,                      */
/* please refer to the startup file (startup_zb32l03x.s).                    */
/******************************************************************************/
void BSP_LOOP_SENDCODE_TIM_IRQHandler(void)
{
 
  if ((BSP_LOOP_SENDCODE_TIM->MSKINTSR & (BASETIM_MSKINTSR_TF)) == (BASETIM_MSKINTSR_TF))
  {
        if ((BSP_LOOP_SENDCODE_TIM->CR & (BASETIM_CR_INTEN)) == (BASETIM_CR_INTEN))
        {
            BSP_LOOP_SENDCODE_TIM->INTCLR |= (BASETIM_INTCLR_INTCLR);
            app_loop_sendcode(&loopctrlinfo); 
           
        }
  }
}

void BSP_LOOP_BACKCODE_DELAYSAMPLE_IRQHandler(void)
{
  if ((BSP_LOOP_BACKCODE_DELAYSAMPLE_TIM->MSKINTSR & (BASETIM_MSKINTSR_TF)) == (BASETIM_MSKINTSR_TF))
  {
        if ((BSP_LOOP_BACKCODE_DELAYSAMPLE_TIM->CR & (BASETIM_CR_INTEN)) == (BASETIM_CR_INTEN))
        {
            BSP_LOOP_BACKCODE_DELAYSAMPLE_TIM->INTCLR |= (BASETIM_INTCLR_INTCLR);
            BSP_LOOP_BACKCODE_DELAYSAMPLE_TIM_DISABLE();
            BSP_LOOP_BACKCODE_TRIGGERSAMPLE_TIM_ENABLE();   
        }
  }
}

#if USE_DMA
void PDMA_IRQHandler(void)
{
  HAL_DMA_IRQHandler(&LOOPADC_DMA);
}

void HAL_DMA_Done_Callback(HAL_DMA_Handle_TypeDef *hDMA, uint32_t channels)
{
    if( channels & HAL_DMA_CHANNEL_ADC )
    {
       
    }
}
#else
void ADC_IRQHandler(void)
{
  uint32_t trigger_source = 0;
  trigger_source = READ_REG(ADC->MSKINTSR);
  /* Clear IT Flag */
  WRITE_REG(ADC->INTCLR, trigger_source);
  if (trigger_source & CONFIG_ADC_CHANNEL_FLAG)
  {
        app_loop_getbackcode(&loopctrlinfo);
  }
  __HAL_GPIO_EXTI_CLEAR_FLAG(BSP_LOOP_BACKCODE_TRIGGER_IN_PORT, BSP_LOOP_BACKCODE_TRIGGER_IN_PIN);
}
#endif
